package com.android.yinghebike.ui.activity

import android.annotation.SuppressLint
import android.content.res.Configuration
import android.content.res.Resources
import android.location.Location
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.View
import android.view.View.*
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.android.baselibrary.dialog.Comm_DialogFragment
import com.android.yinghebike.BuildConfig
import com.android.yinghebike.R
import com.android.yinghebike.bean.BleNavInfo
import com.android.yinghebike.databinding.LayoutActivityNavigationBinding
import com.android.yinghebike.manager.BleManager
import com.android.yinghebike.manager.LanguageManager
import com.android.yinghebike.manager.UnitManager
import com.gyf.immersionbar.ImmersionBar
import com.mapbox.api.directions.v5.DirectionsCriteria
import com.mapbox.api.directions.v5.models.DirectionsRoute
import com.mapbox.api.directions.v5.models.ManeuverModifier
import com.mapbox.api.directions.v5.models.RouteOptions
import com.mapbox.bindgen.Expected
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.EdgeInsets
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.Style.Companion.MAPBOX_STREETS
import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.Plugin
import com.mapbox.maps.plugin.animation.camera
import com.mapbox.maps.plugin.attribution.AttributionPlugin
import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorBearingChangedListener
import com.mapbox.maps.plugin.locationcomponent.location
import com.mapbox.maps.plugin.logo.LogoPlugin
import com.mapbox.navigation.base.TimeFormat
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
import com.mapbox.navigation.base.formatter.DistanceFormatterOptions
import com.mapbox.navigation.base.formatter.UnitType
import com.mapbox.navigation.base.internal.extensions.inferDeviceLocale
import com.mapbox.navigation.base.options.EventsAppMetadata
import com.mapbox.navigation.base.options.NavigationOptions
import com.mapbox.navigation.base.route.RouterCallback
import com.mapbox.navigation.base.route.RouterFailure
import com.mapbox.navigation.base.route.RouterOrigin
import com.mapbox.navigation.base.trip.model.RouteLegProgress
import com.mapbox.navigation.base.trip.model.RouteProgress
import com.mapbox.navigation.core.MapboxNavigation
import com.mapbox.navigation.core.MapboxNavigationProvider
import com.mapbox.navigation.core.arrival.ArrivalObserver
import com.mapbox.navigation.core.directions.session.RoutesObserver
import com.mapbox.navigation.core.formatter.MapboxDistanceFormatter
import com.mapbox.navigation.core.trip.session.*
import com.mapbox.navigation.ui.base.util.MapboxNavigationConsumer
import com.mapbox.navigation.ui.maneuver.api.MapboxManeuverApi
import com.mapbox.navigation.ui.maneuver.model.Maneuver
import com.mapbox.navigation.ui.maps.camera.NavigationCamera
import com.mapbox.navigation.ui.maps.camera.data.MapboxNavigationViewportDataSource
import com.mapbox.navigation.ui.maps.camera.lifecycle.NavigationBasicGesturesHandler
import com.mapbox.navigation.ui.maps.camera.state.NavigationCameraState
import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider
import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowApi
import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowView
import com.mapbox.navigation.ui.maps.route.arrow.model.RouteArrowOptions
import com.mapbox.navigation.ui.maps.route.line.MapboxRouteLineApiExtensions.setRoutes
import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineApi
import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineView
import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineOptions
import com.mapbox.navigation.ui.maps.route.line.model.RouteLine
import com.mapbox.navigation.ui.tripprogress.api.MapboxTripProgressApi
import com.mapbox.navigation.ui.tripprogress.model.*
import com.mapbox.navigation.ui.voice.api.MapboxSpeechApi
import com.mapbox.navigation.ui.voice.api.MapboxVoiceInstructionsPlayer
import com.mapbox.navigation.ui.voice.model.SpeechAnnouncement
import com.mapbox.navigation.ui.voice.model.SpeechError
import com.mapbox.navigation.ui.voice.model.SpeechValue
import com.mapbox.navigation.ui.voice.model.SpeechVolume
import com.mapbox.navigation.utils.internal.logD
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.*


class MapboxNavigationActivity : AppCompatActivity() {

    private lateinit var binding: LayoutActivityNavigationBinding
    private lateinit var mapboxMap: MapboxMap
    private lateinit var mapboxNavigation: MapboxNavigation

    private var isFirstGetLocation: Boolean = false   //是否第一次获取到线路
    var isSyncBike: Boolean = false   //设备是否设置为导航模式
    var totalDistance: Int = 0   //总距离
    lateinit var destination: Point   //终点坐标
    var bearing: Double = 0.0   //旋转角度
    var bleNavInfo: BleNavInfo = BleNavInfo()     //给设备发送的导航数据

    // location puck integration
    private val navigationLocationProvider = NavigationLocationProvider()

    // camera
    private lateinit var navigationCamera: NavigationCamera
    private lateinit var viewportDataSource: MapboxNavigationViewportDataSource
    private val pixelDensity = Resources.getSystem().displayMetrics.density
    private val overviewPadding: EdgeInsets by lazy {
        EdgeInsets(
            140.0 * pixelDensity, 40.0 * pixelDensity, 120.0 * pixelDensity, 40.0 * pixelDensity
        )
    }
    private val landscapeOverviewPadding: EdgeInsets by lazy {
        EdgeInsets(
            30.0 * pixelDensity, 380.0 * pixelDensity, 20.0 * pixelDensity, 20.0 * pixelDensity
        )
    }
    private val followingPadding: EdgeInsets by lazy {
        EdgeInsets(
            180.0 * pixelDensity, 40.0 * pixelDensity, 250.0 * pixelDensity, 40.0 * pixelDensity
        )
    }
    private val landscapeFollowingPadding: EdgeInsets by lazy {
        EdgeInsets(
            30.0 * pixelDensity, 380.0 * pixelDensity, 110.0 * pixelDensity, 40.0 * pixelDensity
        )
    }

    // trip progress bottom view
    private lateinit var tripProgressApi: MapboxTripProgressApi

    // voice instructions
    private var isVoiceInstructionsMuted = false
    private lateinit var maneuverApi: MapboxManeuverApi
    private lateinit var speechAPI: MapboxSpeechApi
    private lateinit var voiceInstructionsPlayer: MapboxVoiceInstructionsPlayer

    // route line
    private lateinit var routeLineAPI: MapboxRouteLineApi
    private lateinit var routeLineView: MapboxRouteLineView
    private lateinit var routeArrowView: MapboxRouteArrowView
    private val routeArrowAPI: MapboxRouteArrowApi = MapboxRouteArrowApi()

    /* ----- Voice instruction callbacks ----- */
    private val voiceInstructionsObserver = VoiceInstructionsObserver { voiceInstructions ->
        speechAPI.generate(
            voiceInstructions, speechCallback
        )
    }

    private val voiceInstructionsPlayerCallback =
        MapboxNavigationConsumer<SpeechAnnouncement> { value ->
            // remove already consumed file to free-up space
            speechAPI.clean(value)
        }

    private val speechCallback =
        MapboxNavigationConsumer<Expected<SpeechError, SpeechValue>> { expected ->
            expected.fold({ error ->
                // play the instruction via fallback text-to-speech engine
                voiceInstructionsPlayer.play(
                    error.fallback, voiceInstructionsPlayerCallback
                )
            }, { value ->
                // play the sound file from the external generator
                voiceInstructionsPlayer.play(
                    value.announcement, voiceInstructionsPlayerCallback
                )
            })
        }

    /* ----- 定位回调 ----- */
    private val locationObserver = object : LocationObserver {
        override fun onNewRawLocation(rawLocation: Location) {
            // not handled
        }

        override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
            // update location puck's position on the map
            navigationLocationProvider.changePosition(
                location = locationMatcherResult.enhancedLocation,
                keyPoints = locationMatcherResult.keyPoints,
            )

            // update camera position to account for new location
            viewportDataSource.onLocationChanged(locationMatcherResult.enhancedLocation)
            viewportDataSource.evaluate()

            Log.i("test", "当前位置海拔" + locationMatcherResult.enhancedLocation.altitude);

            //第一次获取到定位，开始导航
            if (!isFirstGetLocation) {
                if (intent.hasExtra("route")) {
                    val route: DirectionsRoute =
                        intent.getSerializableExtra("route") as DirectionsRoute
                    setRouteAndStartNavigation(listOf(route))
                } else {
                    //获取导航路线
                    findRoute()
                }
                isFirstGetLocation = true
            }
        }
    }

    //偏离导航
    val offRouteObserver = object : OffRouteObserver {
        override fun onOffRouteStateChanged(offRoute: Boolean) {
            // do something when the off route state changes
//            findRoute()
//            CommToast.showToast(applicationContext,"偏离导航",500)
        }
    }

    //导航进度回调
    private val routeProgressObserver = RouteProgressObserver { routeProgress ->
        Log.i("test", "导航进度")
        // update the camera position to account for the progressed fragment of the route
        viewportDataSource.onRouteProgressChanged(routeProgress)
        viewportDataSource.evaluate()

        // show arrow on the route line with the next maneuver
        val maneuverArrowResult = routeArrowAPI.addUpcomingManeuverArrow(routeProgress)
        val style = mapboxMap.getStyle()
        if (style != null) {
//                Log.i("test","maneuverArrowResult:"+ maneuverArrowResult.mapValue {  });
            routeArrowView.renderManeuverUpdate(style, maneuverArrowResult)
        }

        // update top maneuver instructions
        val maneuvers = maneuverApi.getManeuvers(routeProgress)
        maneuvers.fold({ error ->
            Toast.makeText(
                this@MapboxNavigationActivity, error.errorMessage, Toast.LENGTH_SHORT
            ).show()
        }, {
//            binding.maneuverView.visibility = VISIBLE
            binding.maneuverView.renderManeuvers(maneuvers)
        })

        // 底部进度控件
        var result: TripProgressUpdateValue = tripProgressApi.getTripProgress(routeProgress)
        binding.tripProgressView.render(result)
        //剩余距离 result.distanceRemaining
        binding.navProgressView.refreshProgress(routeProgress)

        //获取方向，进行判断
        maneuvers.onValue { list ->
            if (list.isNotEmpty()) {
                val maneuver: Maneuver = list.get(0)
                var direction: Byte = 0
                //判断下一个路口转弯方向
                when (maneuver.primary.modifier) {
                    ManeuverModifier.STRAIGHT -> direction = 0x01;
                    ManeuverModifier.SLIGHT_LEFT -> direction = 0x02;
                    ManeuverModifier.SLIGHT_RIGHT -> direction = 0x03;
                    ManeuverModifier.LEFT -> direction = 0x04;
                    ManeuverModifier.RIGHT -> direction = 0x05;
                    ManeuverModifier.UTURN -> direction = 0x06;
                    ManeuverModifier.SHARP_LEFT -> direction = 0x0D;
                    ManeuverModifier.SHARP_RIGHT -> direction = 0x1D;
                }
                if(maneuver.primary.type == "arrive")  direction = 0x01;     //如果type是arrive，给设备发送直行。 因为将要到达时，地图返回的modifier是左右转
                bleNavInfo.direction = direction;       //方向
                bleNavInfo.altitude = maneuver.maneuverPoint.altitude().toInt();   //海拔
                bleNavInfo.destinationRemainingDistance = routeProgress.distanceRemaining.toInt();    //剩余总距离
                bleNavInfo.nextStepDistance = maneuver.stepDistance.distanceRemaining?.toInt() ?: 0   //下个转弯距离

                Log.i("test", "剩余距离:" + bleNavInfo.nextStepDistance);
                Log.i("test", "modifier:" + maneuver.primary.modifier);


                //给设备发送导航数据
                val data = BleManager.createSendBleData(0x30.toByte(), bleNavInfo.crateData())
                BleManager.getInstance().sendData(data, null)
            }
        }
    }

    private val routesObserver = RoutesObserver { result ->
        if (result.routes.isNotEmpty()) {
            // generate route geometries asynchronously and render them
            CoroutineScope(Dispatchers.Main).launch {
                val result = routeLineAPI.setRoutes(
                    listOf(RouteLine(result.routes.first(), null))
                )

                val style = mapboxMap.getStyle()
                if (style != null) {
                    routeLineView.renderRouteDrawData(style, result)
                }

//                result.onValue { list ->
//
//                }
            }

            // update the camera position to account for the new route
            viewportDataSource.onRouteChanged(result.routes.first())
            viewportDataSource.evaluate()


        } else {
            // remove the route line and route arrow from the map
            val style = mapboxMap.getStyle()
            if (style != null) {
                routeLineAPI.clearRouteLine { value ->
                    routeLineView.renderClearRouteLineValue(
                        style, value
                    )
                }
                routeArrowView.render(style, routeArrowAPI.clearArrows())
            }

            // remove the route reference to change camera position
            viewportDataSource.clearRouteData()
            viewportDataSource.evaluate()
        }
    }

    private val navigationSessionStateObserver = NavigationSessionStateObserver {
        logD("NavigationSessionState=$it", LOG_CATEGORY)
        logD("sessionId=${mapboxNavigation.getNavigationSessionState().sessionId}", LOG_CATEGORY)
    }

    private val onIndicatorBearingChangedListener = OnIndicatorBearingChangedListener {
        bearing = it
    }

    @SuppressLint("MissingPermission")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.resources.configuration.setLocale(LanguageManager.getLocale())
        binding = LayoutActivityNavigationBinding.inflate(layoutInflater)
        setContentView(binding.root)
        mapboxMap = binding.mapView.getMapboxMap()

        ImmersionBar.with(this).statusBarDarkFont(true).navigationBarDarkIcon(true).init()

        // initialize the location puck
        binding.mapView.location.apply {
            this.locationPuck = LocationPuck2D(
                bearingImage = ContextCompat.getDrawable(
                    this@MapboxNavigationActivity, R.drawable.mapbox_navigation_puck_icon
                )
            )
            setLocationProvider(navigationLocationProvider)
            enabled = true
        }

        // initialize Mapbox Navigation
        mapboxNavigation = MapboxNavigationProvider.create(
            NavigationOptions.Builder(this).accessToken(getMapboxAccessTokenFromResources())
                .eventsAppMetadata(
                    EventsAppMetadata.Builder(
                        BuildConfig.APPLICATION_ID, BuildConfig.VERSION_NAME
                    ).build()
                ).build()
        )

        // move the camera to current location on the first update
        mapboxNavigation.registerLocationObserver(object : LocationObserver {
            override fun onNewRawLocation(rawLocation: Location) {
                val point = Point.fromLngLat(rawLocation.longitude, rawLocation.latitude)
                val cameraOptions =
                    CameraOptions.Builder().center(point).zoom(13.0).bearing(bearing).build()
                mapboxMap.setCamera(cameraOptions)
                mapboxNavigation.unregisterLocationObserver(this)
            }

            override fun onNewLocationMatcherResult(
                locationMatcherResult: LocationMatcherResult,
            ) {
                // not handled
            }
        })
        //注册偏离导航
        mapboxNavigation.registerOffRouteObserver(offRouteObserver)
        //注册到达事件
        mapboxNavigation.registerArrivalObserver(object : ArrivalObserver {
            override fun onFinalDestinationArrival(routeProgress: RouteProgress) {
                //到达最终目的地,发送已到达
                mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
                clearRouteAndStopNavigation()

                binding.navArrivedview.visibility = VISIBLE
                Handler().postDelayed(Runnable {
//                    val info0a = Info0a(0, 0, 0, 0x20)
//                    BleManage.getInstance().write(info0a.bytes, null)

                    Log.i("test", "发送到达信息")

                }, 1000)

                routeProgress.fractionTraveled

            }

            override fun onNextRouteLegStart(routeLegProgress: RouteLegProgress) {
                TODO("Not yet implemented")
            }

            override fun onWaypointArrival(routeProgress: RouteProgress) {
                TODO("Not yet implemented")
            }
        })

        val locationComponentPlugin = binding.mapView.location
        locationComponentPlugin.addOnIndicatorBearingChangedListener(
            onIndicatorBearingChangedListener
        )

        // initialize Navigation Camera
        viewportDataSource = MapboxNavigationViewportDataSource(
            binding.mapView.getMapboxMap()
        )
        navigationCamera = NavigationCamera(
            binding.mapView.getMapboxMap(), binding.mapView.camera, viewportDataSource
        )
        binding.mapView.camera.addCameraAnimationsLifecycleListener(
            NavigationBasicGesturesHandler(navigationCamera)
        )
        navigationCamera.registerNavigationCameraStateChangeObserver { navigationCameraState ->
            // shows/hide the recenter button depending on the camera state
            when (navigationCameraState) {
                NavigationCameraState.TRANSITION_TO_FOLLOWING, NavigationCameraState.FOLLOWING -> binding.recenter.visibility =
                    INVISIBLE

                NavigationCameraState.TRANSITION_TO_OVERVIEW, NavigationCameraState.OVERVIEW, NavigationCameraState.IDLE -> binding.recenter.visibility =
                    VISIBLE
            }
        }
        if (this.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            viewportDataSource.overviewPadding = landscapeOverviewPadding
        } else {
            viewportDataSource.overviewPadding = overviewPadding
        }
        if (this.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            viewportDataSource.followingPadding = landscapeFollowingPadding
        } else {
            viewportDataSource.followingPadding = followingPadding
        }

        //设置距离单位
        var unitTypeInt = UnitManager.getUnitType()
        var unitType: UnitType;
        if (unitTypeInt == 0) {
            unitType = UnitType.METRIC   //公制
        } else {
            unitType = UnitType.IMPERIAL   //英制
        }
        // 顶部箭头
        maneuverApi = MapboxManeuverApi(
            //设置距离单位
            MapboxDistanceFormatter(
                DistanceFormatterOptions.Builder(this).unitType(unitType)
                    .build()
            )
        )

        // initialize bottom progress view
        tripProgressApi = MapboxTripProgressApi(
            TripProgressUpdateFormatter.Builder(this).distanceRemainingFormatter(
                DistanceRemainingFormatter(
                    mapboxNavigation.navigationOptions.distanceFormatterOptions
                )
            ).timeRemainingFormatter(TimeRemainingFormatter(this))
                .percentRouteTraveledFormatter(PercentDistanceTraveledFormatter())
                .estimatedTimeToArrivalFormatter(
                    EstimatedTimeToArrivalFormatter(this, TimeFormat.NONE_SPECIFIED)
                ).build()
        )

        // 语音播放相关
        speechAPI = MapboxSpeechApi(
            this, getMapboxAccessTokenFromResources(), Locale.CHINESE.language
        )
        voiceInstructionsPlayer = MapboxVoiceInstructionsPlayer(
            this, Locale.CHINESE.language
        )

        // 线路配置
        val mapboxRouteLineOptions = MapboxRouteLineOptions.Builder(this)
            .withVanishingRouteLineEnabled(true)    //走过的路变色
            .displaySoftGradientForTraffic(true)      //显示交通情况
            .softGradientTransition(30)
            .withRouteLineBelowLayerId("road-label")
            .build()
        routeLineAPI = MapboxRouteLineApi(mapboxRouteLineOptions)
        routeLineView = MapboxRouteLineView(mapboxRouteLineOptions)
        val routeArrowOptions = RouteArrowOptions.Builder(this).build()
        routeArrowView = MapboxRouteArrowView(routeArrowOptions)

        // load map style
        mapboxMap.loadStyleUri(MAPBOX_STREETS) { style ->
            routeLineView.initializeLayers(style)
            // add long click listener that search for a route to the clicked destination
            binding.mapView.gestures.addOnMapLongClickListener { point ->
//                findRoute(point)
                true
            }
        }

        //到达控件
        binding.navArrivedview.setExitClick(object : View.OnClickListener {
            override fun onClick(p0: View?) {
                finish()
            }
        })
        // 退出导航按钮
        binding.stop.setOnClickListener {
            clearRouteAndStopNavigation()
            finish()
        }
        binding.recenter.setOnClickListener {
            navigationCamera.requestNavigationCameraToFollowing()
        }
        binding.routeOverview.setOnClickListener {
            navigationCamera.requestNavigationCameraToOverview()
            binding.recenter.showTextAndExtend(2000L)
        }
        binding.soundButton.setOnClickListener {
            // mute/unmute voice instructions
            isVoiceInstructionsMuted = !isVoiceInstructionsMuted
            if (isVoiceInstructionsMuted) {
                binding.soundButton.muteAndExtend(2000L)
                voiceInstructionsPlayer.volume(SpeechVolume(0f))
            } else {
                binding.soundButton.unmuteAndExtend(2000L)
                voiceInstructionsPlayer.volume(SpeechVolume(1f))
            }
        }

        // start the trip session to being receiving location updates in free drive
        // and later when a route is set, also receiving route progress updates
        mapboxNavigation.startTripSession()

        //进页面强制设备进入导航模式
        setBikeDisPlayState(true);

        registObserver()

        //隐藏地图logo和问号
        val logoPlugin: LogoPlugin? = binding.mapView.getPlugin(Plugin.MAPBOX_LOGO_PLUGIN_ID)
        if (logoPlugin != null) {
            logoPlugin.enabled = false
        }
        val attributionPlugin: AttributionPlugin? =
            binding.mapView.getPlugin(Plugin.MAPBOX_ATTRIBUTION_PLUGIN_ID)
        if (attributionPlugin != null) {
            attributionPlugin.enabled = false
        }

        //进度控件
        binding.navProgressView.setExitClick {
            Comm_DialogFragment.showCommDialog(
                this, "", getString(R.string.nav_exit_tips), getString(R.string.comm_btn_ok), getString(R.string.comm_btn_cancel),
                {
                    clearRouteAndStopNavigation()
                    finish()
                }, null
            )
        }
    }

    //设置设备是否进入导航模式
    fun setBikeDisPlayState(isNav: Boolean) {
        if (isNav) {
            val arr = BleManager.createControlData(0x05.toByte())
            BleManager.getInstance().sendData(arr, null)
        } else {
            val arr = BleManager.createControlData(0x06.toByte())
            BleManager.getInstance().sendData(arr, null)
        }
    }

    fun registObserver() {
        mapboxNavigation.registerRoutesObserver(routesObserver)
        mapboxNavigation.registerNavigationSessionStateObserver(navigationSessionStateObserver)
        mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
        mapboxNavigation.registerLocationObserver(locationObserver)
        mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver)
    }

    fun unRegistObserver() {
        mapboxNavigation.unregisterRoutesObserver(routesObserver)
        mapboxNavigation.unregisterNavigationSessionStateObserver(navigationSessionStateObserver)
        mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
        mapboxNavigation.unregisterLocationObserver(locationObserver)
        mapboxNavigation.unregisterVoiceInstructionsObserver(voiceInstructionsObserver)
    }

    override fun onDestroy() {
        super.onDestroy()
        unRegistObserver()
        routeLineAPI.cancel()
        routeLineView.cancel()
        mapboxNavigation.onDestroy()
        maneuverApi.cancel()
        speechAPI.cancel()
        voiceInstructionsPlayer.shutdown()

        //设备退出导航模式
        setBikeDisPlayState(false);
    }

    //搜索路线
    private fun findRoute() {
        val origin = navigationLocationProvider.lastLocation?.let {
            Point.fromLngLat(it.longitude, it.latitude)
        } ?: return
        val destination = intent.getSerializableExtra("destination") as Point

        val routeOptions = RouteOptions.builder()
            .applyDefaultNavigationOptions(DirectionsCriteria.PROFILE_CYCLING)     //搜索自行车路线
//            .applyLanguageAndVoiceUnitOptions(this)
            .coordinatesList(listOf(origin, destination))
//            .layersList(listOf(mapboxNavigation.getZLevel(), null))
//            .bearingsList(
//                listOf(
//                    Bearing.builder()
//                        .angle(navigationLocationProvider.lastLocation!!.bearing.toDouble())
//                        .degrees(45.0)
//                        .build(),
//                    null
//                )
//            )
            .alternatives(true)
            .build()
        mapboxNavigation.requestRoutes(
            routeOptions,
            routesReqCallback
        )

    }

    private val routesReqCallback: RouterCallback = object : RouterCallback {
        override fun onRoutesReady(routes: List<DirectionsRoute>, routerOrigin: RouterOrigin) {
            setRouteAndStartNavigation(routes)
            if (routes.isNotEmpty()) {
                Log.i("test", "获取到路线：" + routes.size)
            }
        }

        override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {

        }

        override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
            Log.i("test", "获取路线失败：" + reasons[0].message)
        }
    }

    //开始导航
    private fun setRouteAndStartNavigation(route: List<DirectionsRoute>) {
        // set route
        mapboxNavigation.setRoutes(route)


        // show UI elements
        binding.maneuverView.visibility = VISIBLE
        binding.llRightBtn.visibility = VISIBLE
//        binding.tripProgressCard.visibility = VISIBLE


//        binding.soundButton.visibility = VISIBLE
//        binding.routeOverview.visibility = VISIBLE

        binding.routeOverview.showTextAndExtend(2000L)
        binding.soundButton.unmuteAndExtend(2000L)

        // move the camera to overview when new route is available
        navigationCamera.requestNavigationCameraToOverview()

        binding.recenter.performClick()
    }

    private fun clearRouteAndStopNavigation() {
        // clear
        mapboxNavigation.setRoutes(listOf())

        // hide UI elements
        binding.maneuverView.visibility = GONE
        binding.llRightBtn.visibility = GONE
//        binding.tripProgressCard.visibility = GONE

//        binding.soundButton.visibility = GONE
//        binding.maneuverView.visibility = GONE
//        binding.routeOverview.visibility = GONE
//        binding.tripProgressCard.visibility = GONE
//        binding.recenter.visibility = GONE

    }

    private fun getMapboxAccessTokenFromResources(): String {
        return getString(R.string.mapbox_access_token)
    }

    private companion object {
        private const val LOG_CATEGORY = "MapboxNavigationActivity"
    }
}
